home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / util / shell / axuucp_0_1.lha / axsh / rexx / ax2uucp.rexx < prev    next >
Encoding:
OS/2 REXX Batch file  |  1995-03-22  |  12.4 KB  |  422 lines

  1. /****** axuucp/ax2uucp *******************************************************
  2. *
  3. *   NAME
  4. *    ax2uucp - Create UUCP batches from unread AXsh news articles
  5. *
  6. *   SYNOPSIS
  7. *    rx ax2uucp.rexx [user]
  8. *
  9. *   DESCRIPTION
  10. *    ax2uucp looks at the user's ~/.rnnewsrc file, collects all unread
  11. *    news articles, joins them together in one ore more UUCP batches
  12. *    and marks these articles as read in user's ~/.rnnewsrc file.
  13. *    If there is pending mail for the given user, ax2uucp creates the
  14. *    spoolfiles for the mail as well and removes it from the system
  15. *    mailbox.
  16. *
  17. *    The user must have a ~user/.rnnrewsrc file.  Otherwise no news
  18. *    articles will be exported.  It is recommended that the user
  19. *    subscribes newsgroups via rn.  Only articles of subscribed groups
  20. *    will be exported of course.
  21. *
  22. *   NOTES
  23. *    The created spool files get the following UUCP priorities:
  24. *
  25. *        News batches        D.<system>B<seq>
  26. *        Mail            D.<system>A<seq>
  27. *        Control files        C.<system>N<seq>
  28. *        Command files        D.<system>X<seq>
  29. *
  30. *   BUGS
  31. *    List LFORMAT "%l" returns text (e.g. "empty" instead of "0") in
  32. *    some situations.  Due to localization problems we decided to treat
  33. *    all files with non-digit characters in it's file size like empty
  34. *    files and ignore them.
  35. *
  36. *   AUTHOR
  37. *    Tobias Ferber <tf@ganymed.hall.sub.org>
  38. *    The mbox scanner and genseq() are Copyright (c)1994 by Tobias Walter
  39. *
  40. ******************************************************************************
  41. *
  42. */
  43.  
  44. if (arg() < 1) | (words(arg(1)) < 1) then do
  45.   say 'usage: rx ax2uucp.rexx [user]'
  46.   exit
  47.   end
  48.  
  49. username = arg(1)
  50.  
  51. newsrc   = axconfig("home") || username || "/.rnnewsrc"
  52. newsrc_  = newsrc'_'
  53. axnews   = axconfig("news")
  54. tempfile = axconfig("tempdir") || "ax2uuccp." || pragma('Id')
  55.  
  56. spooldir = strfmt(axconfig("axuucp.spooldir"),"%u",username)
  57. seqfile  = axconfig("axuucp.seqfile")
  58.  
  59. bpb_max  = axconfig("axuucp.batchlimit"); if words(bpb_max) < 1 then bpb_max=65535
  60. bpb      = 0  /* #of bytes per batch */
  61.  
  62. axmail   = axconfig("mail")
  63. aka      = axconfig("thismachine")
  64. nodename = aka; p=pos('.',nodename); if p>1 then nodename=left(nodename,p-1)
  65. mbox     = axmail || username
  66. toaddr   = username /*'@'aka*/
  67.  
  68. xmail    = 0 /* #of exported mail messages */
  69. xnews    = 0 /* #of exported news articles */
  70.  
  71. /**/
  72.  
  73. if ~exists(axnews) | ~exists(axmail) | (words(nodename) < 1) then do
  74.   say 'ax2uucp: Error in "/etc/rc" (%mail:, %news: or %thismachine:)'
  75.   exit 10
  76.   end
  77.  
  78. if ~exists(spooldir) then do
  79.   say 'ax2uucp: No such spool directory: "'spooldir'"'
  80.   exit 10
  81.   end
  82.  
  83.  
  84. /* News */
  85.  
  86. if exists(newsrc_) then address command 'Delete QUIET "'newsrc_'"'
  87.  
  88. if open('rc',newsrc,'Read') then do
  89.  
  90.   do until eof('rc')
  91.     str= readln('rc')
  92.     if words(str) > 0 then do
  93.       parse var str lhs ' ' rhs
  94.       gflag= right(lhs,1)  /* ':' = subscribed, '!' = unsubscribed */
  95.       gname= left(lhs,length(lhs)-1)
  96.       gdir= axnews || translate(gname,'/','.')
  97.       gex=0 /* #of articles exported for this group */
  98.  
  99.       if gflag = ':' then do
  100.         if exists(gdir'/.lowest') & exists(gdir'/.next') then do
  101.           call open('seq',gdir'/.lowest','Read'); glowest= readln('seq'); call close('seq')
  102.           call open('seq',gdir'/.next','Read'); gnext= readln('seq'); call close('seq')
  103.  
  104.           address command 'List FILES DIR "'gdir'" LFORMAT "%n(%l)" PAT "~(.#?)" > "'tempfile'"'
  105.           call open('tmp',tempfile,'Read')
  106.           do until eof('tmp')
  107.             art= readln('tmp')
  108.             if words(art) > 0 then do
  109.               parse var art artno '(' bpa ')'
  110.               if words(compress(bpa,"0123456789")) > 0 then bpa=0
  111.               if (bpa>0) & ~inset(artno,rhs) then do
  112.                 if (bpb=0) | ((bpb+bpa+18)>bpb_max) then do
  113.                   if bpb>0 then bpb= spool_news(tempbatch,seq)
  114.                   seq = genseq(seqfile)
  115.                   tempbatch = spooldir || spoolfile('D',nodename,'B',seq) || ".TMP";
  116.                   end
  117.                 address command 'Echo >> "'tempbatch'"' || '"#! rnews' right(bpa,8,'0')'"'
  118.                 address command 'Type >> "'tempbatch'"' || '"'gdir'/'artno'"'   /* unset NOCLOBBER ! */
  119.                 bpb = bpb + 18 + bpa   /* 18 bytes "#! rnews 00000000\n" */
  120.                 gex=gex+1
  121.                 end
  122.               end
  123.             end
  124.           call close('tmp')
  125.  
  126.           address command 'Delete QUIET FILE "'tempfile'"'
  127.           rhs="0"
  128.           if (gnext>0) & (gnext>glowest+1) then rhs= rhs'-'gnext-1
  129.           /*say gname || gflag rhs 'of' gnext-glowest 'in ['glowest'..'gnext-1'], exported:' gex*/
  130.           xnews= xnews+gex
  131.           end
  132.  
  133.         else do
  134.           say 'Newsgroup "'gname'" not available -- will be unsubscribed'
  135.           gflag= '!'
  136.           end
  137.  
  138.         end
  139.       address command 'Echo >> "'newsrc_'"' '"'gname || gflag rhs'"'
  140.       end
  141.     end
  142.  
  143.   call close('rc')
  144.   address command 'Copy QUIET FROM "'newsrc_'" TO "'newsrc'"'
  145.   address command 'Delete QUIET FILE "'newsrc_'"'
  146.   if bpb>0 then bpb= spool_news(tempbatch,seq)
  147.   end
  148.  
  149. else do
  150.   say 'ax2uucp: user' username 'has no ~/.rnnewsrc'
  151.   end
  152.  
  153.  
  154. /* Mail */
  155.  
  156. if exists(mbox) then do
  157.   if open('in',mbox,'Read') then do
  158.     l = readln('in')
  159.     state='start';
  160.  
  161.     do while ~eof('in')
  162.       select
  163.  
  164.         when state = 'start' then do
  165.           if word(l,1)~='From' then do
  166.             say 'From_ expected in line 1'
  167.             exit 20
  168.             end
  169.           else do
  170.             orig = l
  171.             state = 'next'
  172.             end
  173.           end
  174.  
  175.         when state = 'next' then do
  176.           call open('fp',tempfile,'Write')
  177.           call writeln('fp',orig)  /* From_ */
  178.           /*if upper(left(l,4)) = 'TO: ' then toaddr= rfcaddr(substr(l,5))*/
  179.           /*else*/ if l='' then state='body null'
  180.           call writeln('fp',l)
  181.           state = 'header'
  182.           end
  183.  
  184.         when state = 'header' then do
  185.           /*if upper(left(l,4)) = 'TO: ' then toaddr= rfcaddr(substr(l,5))*/
  186.           /*else*/ if l='' then state='body null'
  187.           call writeln('fp',l)
  188.           end
  189.  
  190.         when state = 'body null' then do
  191.           if word(l,1)='From' then do
  192.             orig = l
  193.             state = 'body from'
  194.             end
  195.           else do
  196.             call writeln('fp',l)
  197.             if l~='' then state = 'body nonnull'
  198.             end
  199.           end
  200.  
  201.         when state = 'body from' then do
  202.           if right(word(l,1),1)=':' then do
  203.             call close('fp')
  204.             call spool_mail(tempfile,genseq(seqfile),toaddr)
  205.             /*toaddr= username'@'aka*/
  206.             xmail= xmail+1
  207.             state= 'have next'
  208.             end
  209.           else do
  210.             call writeln('fp',orig)
  211.             call writeln('fp',l)
  212.             if l='' then state = 'body null'
  213.                     else state = 'body nonull'
  214.             end
  215.           end
  216.  
  217.         when state = 'body nonnull' then do
  218.           call writeln('fp',l)
  219.           if l='' then state = 'body null'
  220.           end
  221.  
  222.         otherwise nop
  223.         end
  224.  
  225.       if state = 'have next' then state = 'next'
  226.                              else l= readln('in')
  227.       end
  228.  
  229.     call close('in')
  230.  
  231.     if word(state,1) = 'body' then do
  232.       call close('fp')
  233.       call spool_mail(tempfile,genseq(seqfile),toaddr)
  234.       xmail= xmail+1
  235.       end
  236.  
  237.     if exists(tempfile) then address command 'Delete QUIET "'tempfile'"'
  238.     address command 'Delete QUIET "'mbox'"'
  239.     end
  240.  
  241.   else do
  242.     say 'ax2uucp: could not read system mbox for user "'username'"'
  243.     end
  244.   end
  245.  
  246. /*
  247. else do
  248.   say 'ax2uucp: no pending mail for user' username
  249.   end
  250. */
  251.  
  252. say 'ax2uucp: export for user "'username'":' xmail 'mail message(s),' xnews 'news article(s)'
  253. exit
  254.  
  255.  
  256. /*
  257. */
  258.  
  259.  
  260. /* find out whether an article is member of a set of articles */
  261.  
  262. inset: procedure
  263.   arg n,set
  264.   do while words(set) > 0
  265.     parse var set r ',' set
  266.     if pos('-',r) > 0 then do
  267.       parse var r r0 '-' r1
  268.       if ((r0 <= n) & (n <= r1)) then return 1
  269.       end
  270.     else if r=n then return 1
  271.     end
  272.   return 0
  273.  
  274.  
  275. /* return the name of a spoolfile */
  276.  
  277. spoolfile: procedure
  278.   parse arg type,node,pri,seq
  279.   return upper(left(type,1)) || "." || left(node,min(length(node),7)) || upper(left(pri,1)) || seq
  280.  
  281.  
  282. /* create the spoolfiles for an uncompressed news batchfile */
  283.  
  284. spool_news: procedure expose username nodename spooldir
  285.   parse arg fname,seq
  286.  
  287.   dname_here = spoolfile('D',username,'B',seq);  dname_there = spoolfile('D',nodename,'B',seq)
  288.   xname_here = spoolfile('D',username,'X',seq);  xname_there = spoolfile('X',nodename,'B',seq)
  289.  
  290.   dfile = spooldir || dname_here; 
  291.   xfile = spooldir || xname_here
  292.   cfile = spooldir || spoolfile('C',username,'N',seq)
  293.  
  294.   address command 'cat < "'fname'" > "'dfile'"'
  295.   /*address command 'compress -c < "'fname'" > "'dfile'"'*/
  296.   address command 'Delete QUIET FILE "'fname'"'
  297.  
  298.   address command 'Echo > "'xfile'" "' || 'U news' nodename      || '*N' ||,
  299.                                           'R postmaster'         || '*N' ||,
  300.                                           'Z'                    || '*N' ||,
  301.                                           'F' dname_there        || '*N' ||,
  302.                                           'I' dname_there        || '*N' ||,
  303.                                           'C rnews'                      ||  '"'
  304.  
  305.   address command 'Echo > "'cfile'" "' || 'S' dname_here dname_there 'root' '-' dname_here '0666' || '*N' ||,
  306.                                           'S' xname_here xname_there 'root' '-' xname_here '0666' || '"'
  307.  
  308.   return 0
  309.  
  310.  
  311. /* create the spoolfiles for a mailfile */
  312.  
  313. spool_mail: procedure expose username nodename spooldir
  314.   parse arg fname,seq,toaddr
  315.  
  316.   dname_here = spoolfile('D',username,'B',seq);  dname_there = spoolfile('D',nodename,'B',seq)
  317.   xname_here = spoolfile('D',username,'X',seq);  xname_there = spoolfile('X',nodename,'B',seq)
  318.  
  319.   dfile = spooldir || dname_here; 
  320.   xfile = spooldir || xname_here
  321.   cfile = spooldir || spoolfile('C',username,'N',seq)
  322.  
  323.   address command 'Copy QUIET CLONE FROM "'fname'" TO "'dfile'"'
  324.   address command 'Delete QUIET FILE "'fname'"'
  325.  
  326.   address command 'Echo > "'xfile'" "' || 'U daemon' nodename    || '*N' ||,
  327.                                           'R postmaster'         || '*N' ||,
  328.                                           'Z'                    || '*N' ||,
  329.                                           'F' dname_there        || '*N' ||,
  330.                                           'I' dname_there        || '*N' ||,
  331.                                           'C rmail' nodename             ||  '"'
  332.  
  333.   address command 'Echo > "'cfile'" "' || 'S' dname_here dname_there 'root' '-' dname_here '0666' || '*N' ||,
  334.                                           'S' xname_here xname_there 'root' '-' xname_here '0666' || '"'
  335.   return 0
  336.  
  337.  
  338.  
  339. /*@<genseq><axconfig><strfmt>*/
  340.  
  341. /* from `mbox2ums.rexx' by Tobias Walter */
  342.  
  343. genseq: procedure
  344.   parse arg seqfile
  345.  
  346.   call open('seq',seqfile,'Read')
  347.   seq= readln('seq')
  348.   call close('seq')
  349.  
  350.   if seq>1679616 then seq=1  /* 1679616 = 36*36*36*36 */
  351.  
  352.   call open('seq',seqfile,'Write')
  353.   call writeln('seq',seq+1)
  354.   call close('seq')
  355.  
  356.   uuseq= ""
  357.   do i=0 to 3
  358.     c= seq//36; seq= seq%36    /* 36 = [0-9]+[a-z] */
  359.     if c>=10 then c= d2c(c+87) /* 87 = c2d('a')-10 */
  360.     uuseq= c || uuseq
  361.     end
  362.  
  363.   return uuseq
  364.  
  365.  
  366. /* get an AXsh configuration value */
  367.  
  368. axconfig: procedure
  369.   tempfile = "T:axconfig." || pragma('Id')
  370.   rc_index  = "AXsh:rexx/rc.index"
  371.   var_val=""; var_file=""; var_defval="";
  372.  
  373.   parse upper arg var_name
  374.   if left(var_name,1) ~= '%' then var_name = '%'var_name
  375.   if right(var_name,1) ~= ':' then var_name = var_name':'
  376.  
  377.   if open('idx',rc_index,'Read') then do
  378.     do until (eof('idx') | (var_file~=''))
  379.       str= translate(readln('idx'),' ',d2c(9))
  380.       if words(str) > 0 then do
  381.         parse var str vname ' ' fname '"' defval '"'
  382.         if upper(vname) = var_name then do
  383.           var_file= strip(fname,'B',' 'd2c(9))
  384.           var_defval= defval
  385.           end
  386.         end
  387.       end
  388.     call close('idx')
  389.     end
  390.   else say 'Could not read "'rc_index'"'
  391.  
  392.   if words(var_file) > 0 then do
  393.     if open('rc',var_file,'Read') then do
  394.       do until (eof('rc') | (var_val~=''))
  395.         str= translate(readln('rc'),' ',d2c(9))
  396.         if upper(word(str,1)) = var_name then var_val = strip(readln('rc'),'B',' 'd2c(9))
  397.         end
  398.       call close('rc')
  399.       end
  400.     else say 'Could not examine "'var_file'" for' var_name
  401.     end
  402.   else do
  403.     if words(var_defval) > 0 then var_val= var_defval
  404.     else say 'No such config variable:' var_name
  405.     end
  406.  
  407.   return var_val
  408.  
  409.  
  410. /* substitute all occurences of 'fmt' in 'str' by 'val' */
  411.  
  412. strfmt: procedure
  413.   parse arg str,fmt,val
  414.   p= pos(fmt,str)
  415.   do while p>0
  416.     str= left(str,p-1) || val || substr(str,p+length(fmt))
  417.     p= pos(fmt,str)
  418.     end
  419.   return str
  420.  
  421.  
  422.